package com.example.mytips.structure;

import com.example.mytips.utils.DialogUtils;
import com.example.mytips.utils.SelectFileInfo;
import com.example.mytips.utils.TextInsertUtil;
import com.intellij.lang.Language;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.ui.ListUtil;
import com.intellij.ui.components.JBScrollPane;
import icons.SdkIcons;
import org.apache.http.util.TextUtils;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.awt.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MyClassStructureAction extends AnAction {

    List<String> lineList;
    List<ClassEntity> classList;

    @Override
    public void actionPerformed(AnActionEvent e) {

        // 获取当前项目
        Project project = e.getProject();

        ///上下文
        DataContext context = e.getDataContext();

        ///当前文件
        PsiFile psiFile = CommonDataKeys.PSI_FILE.getData(context);

        //编辑器
        Editor editor = CommonDataKeys.EDITOR.getData(context);
        if (editor == null) return;
        // 文档
        Document document = editor.getDocument();
        // 光标位置
        int offset = editor.getCaretModel().getOffset();

        // 光标的所在的行号
        int cursorLine = document.getLineNumber(offset);

        // 一行一行读取文件
        lineList = new ArrayList<>();
        StringBuilder stringBuilder = new StringBuilder();
        try {
            assert psiFile != null;
            try (InputStream inputStream = psiFile.getVirtualFile().getInputStream();
                 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    // 在这里处理每一行的内容
                    lineList.add(line);
                    stringBuilder.append(line);
                }
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        if (lineList.size() < 1) {
            System.out.println("空的");
            return;
        }


        classList = new ArrayList<>();
        ClassEntity existClassEntity = null;
        //取出类
        for (int line = 0; line < lineList.size(); line++) {
            String lineStr = lineList.get(line);

            ClassEntity classEntity = isClass(lineStr, line);
            if (classEntity != null) {
                ///出现新的类
                existClassEntity = classEntity;
                classList.add(classEntity);
                System.out.println("类名 " + classEntity.name);
            } else {
                ///在现有类中
                MethodEntity methodEntity = isMethod(lineStr, line);
                if (methodEntity != null) {
                    ///在现有类中，出现新的方法
                    System.out.println("方法名 " + methodEntity.name);
                    if (existClassEntity != null) {
                        existClassEntity.methodList.add(methodEntity);
                    }
                } else {
                    System.out.println(lineStr);
                }

            }
        }

        if (classList.size() <= 0) return;

        FlutterStructureDialog dialogWrapper = new FlutterStructureDialog(e, classList, psiFile.getName(), editor,cursorLine);
        DialogUtils.screenCenterShow(dialogWrapper);
        dialogWrapper.show();

    }

    /**
     * 是否是方法
     */
    MethodEntity isMethod(String lineStr, int line) {
        if (TextUtils.isEmpty(lineStr)) return null;

        ///成员变量和成员方式才会是这个开头
        String blankStr = "  ";

        ///几个过滤条件
        if (!lineStr.startsWith(blankStr)) {
            return null;
        }

        ///去掉最前面的两个空格
        String newLineStr = lineStr.substring(blankStr.length());
        ///如果前面还有两个空格，那一定不是方法
        if (newLineStr.startsWith(blankStr)) {
            return null;
        }

        ///这是注释行
        if (newLineStr.startsWith("*") || newLineStr.startsWith("//")) {
            return null;
        }

        int smallLeftPos = lineStr.indexOf("(");
        int smallRightPos = lineStr.indexOf(")");
        int bigLeftPos = lineStr.indexOf("{");
        int bigRightPos = lineStr.indexOf("}");
        int endPos = lineStr.indexOf(";");

        boolean end = lineStr.endsWith(";");
        boolean bigLeftEnd = lineStr.endsWith("{");
        boolean bigRightEnd = lineStr.endsWith("}");

        /// 找不到(
        if (smallLeftPos == -1) {
            return null;
        }

        ///成员变量的特征，这明显不是方法
        if (lineStr.contains("=>") || lineStr.startsWith("late")) {
            return null;
        }


        if (lineStr.contains("=")) {
            int equalPos = lineStr.indexOf("=");
            if (smallLeftPos < equalPos && equalPos < smallRightPos) {

            } else {
                return null;
            }
        }

        /// 方法特征
        ///  void test() {}
        boolean style1 = smallLeftPos < smallRightPos && bigLeftPos < bigRightPos && bigRightEnd;
        ///  void test() {
        boolean style2 = smallLeftPos < smallRightPos && bigLeftEnd;
        ///  void test();
        boolean style3 = smallLeftPos < smallRightPos && end && lineStr.endsWith(");");
        ///  void test(
        boolean style4 = lineStr.trim().endsWith("(");
        ///  void test({
        boolean style5 = lineStr.trim().endsWith("({");
        ///  test(String kye,
        boolean style6 = lineStr.trim().endsWith(",");
        if (style1 ||
                style2 ||
                style3 ||
                style4 ||
                style5 ||
                style6

        ) {
            MethodEntity methodEntity = new MethodEntity();
            ///所在行
            methodEntity.startLineNum = line;

            ///方法名 和 返回值赋值
            String methodName = lineStr.substring(0, smallLeftPos);

            ///如果>为结尾 形如：Future<IFFR<L>> getFriends<L, E>
            if (methodName.endsWith(">")) {
                int lastIndexOf = methodName.lastIndexOf("<");
                if (lastIndexOf != -1) {
                    methodName = methodName.substring(0,lastIndexOf);
                }
            }

            /// "Widget build",用空格切开，前面的就是返回值，后面的就是方法名
            int lastIndexOf = methodName.lastIndexOf(" ");
            if (lastIndexOf == -1) {
                methodEntity.name = methodName;
            } else {
                methodEntity.name = methodName.substring(lastIndexOf);
                methodEntity.resultValue = methodName.substring(0, lastIndexOf).trim();
            }

            ///方法注释 从当前行往上走，直到遇到"  } xxx"
            ClassEntity classEntity = classList.get(classList.size() - 1);
            int lineStart = -1;
            if (classEntity.methodList.isEmpty()) {
                //第一个方法
                lineStart = classEntity.startLineNum;
            } else {
                //不是第一个方法
                MethodEntity method = classEntity.methodList.get(classEntity.methodList.size() - 1);
                lineStart = method.startLineNum;
            }

            ///获取注释
            List<String> noteList = new ArrayList<>();
            for (int i = line - 1; i > lineStart; i--) {
                String noteStr = lineList.get(i);
                String trim = noteStr.trim();

                if (TextUtils.isEmpty(noteStr) || trim.startsWith("@")) {
                    continue;
                }


                ///去掉最前面的两个空格
                String newNoteStr = noteStr.substring(blankStr.length());
                if ( trim.startsWith("/")) {
                    ///这是注释行
                    noteList.add(noteStr);
                    break;
                } else if (trim.startsWith("*")) {
                    noteList.add(noteStr);
                } else {
                    break;
                }

            }

            ///注释格式化
            StringBuilder noteStr = new StringBuilder();
            for (int i = noteList.size() - 1; i >= 0; i--) {
                String noteLine = noteList.get(i);
                noteLine = noteLine.replace("/", "");
                noteLine = noteLine.replace("*", "");
                if (noteLine.length() > 1) {
                    noteStr.append(noteLine);
                }
            }

            methodEntity.note = noteStr.toString().trim();
            return methodEntity;
        }

        return null;
    }

    /**
     * 是否是类
     */
    ClassEntity isClass(String lineStr, int line) {
        if (TextUtils.isEmpty(lineStr)) return null;

        String classStart = "class ";
        String abstractClassStart = "abstract class ";
        String extensionStart = "extension ";
        String enumStart = "enum ";
        String mixinStart = "mixin ";

        boolean isClassStart = lineStr.startsWith(classStart);
        boolean isAbstractClassStart = lineStr.startsWith(abstractClassStart);
        boolean isExtensionStart = lineStr.startsWith(extensionStart);
        boolean isEnumStart = lineStr.startsWith(enumStart);
        boolean isMixinStart = lineStr.startsWith(mixinStart);

        if (isClassStart || isAbstractClassStart || isExtensionStart || isEnumStart || isMixinStart) {

            //取出类名
            String className = "";
            String newLineStr = lineStr;
            if (isClassStart) {
                newLineStr = newLineStr.substring(classStart.length());
            } else if (isAbstractClassStart) {
                newLineStr = newLineStr.substring(abstractClassStart.length());
            } else if (isExtensionStart) {
                newLineStr = newLineStr.substring(extensionStart.length());
            } else if (isEnumStart) {
                newLineStr = newLineStr.substring(enumStart.length());
            } else if (isMixinStart) {
                newLineStr = newLineStr.substring(mixinStart.length());
            }
            String[] splitList = newLineStr.split(" ");
            className = splitList[0];

            ClassEntity classEntity = new ClassEntity();
            classEntity.startLineNum = line;
            classEntity.name = className.trim();
            String[] split = lineStr.split(classEntity.name);

            if (split.length > 0) {
                classEntity.type = split[0].trim();
            }
            return classEntity;
        }

        return null;
    }

}
